import React from "react";

//如果不是一个有效的ReactNode，那就包一个span
function getValidChildren(children) {
  return React.isValidElement(children)
    ? children
    : React.createElement("span", null, children);
}

/**
 * 条件渲染组件
 * 目的是干掉代码里的短路和三元表达式，不好看而且太乱了
 * 这个东西可以把一切逻辑组件化，render内再也没有讨厌的逻辑判断了 /yeah
 * 哦对还有个map，我在想这玩意需不需要
 * 如果有人觉得还是以前"混乱"的代码更好写（确实少了大概十几个字节）或者更好看
 * 那么他肯定没有强迫症，不是个好程序员
 *
 * 2018/12/4 ZaraNengap
 * 今日发现一个小缺陷
 * 不能实现类似的结构：
 * 如果
 *
 * array = [];
 *
 * //可以运行
 * { array.length > 0 && <span>array[0].name</span> }
 *
 * //报错
 * <If value={array.length > 0}>
 *     <span>{array[0].name}</span>
 * </If>
 *
 * 因为就算组件内部返回的是null，组件也并不能阻止内部children代码的执行，但是短路可以
 * React 16.* 有了componentDidCatch 可以搞定, 15.* 没有类似的异常捕获生命周期
 * 尝试在render里加入try-catch也没用，除非你加到父组件上
 * 暂时没想到什么好方法解决, 组件也变得不完美了, so sad :(
 *
 */
class Condition extends React.Component {
  getChildren = () => {
    const { children, debug } = this.props;
    let resultList = [];
    let noNeedElse = false;
    let hasElse = false;
    //毕竟ElseIF的判断是只出现前面第一个判断为true的，所以如果已经有了后面都不显示
    let hasOneValidIf = false;
    React.Children.map(children, (child) => {
      let conditionName = child.props._conditionName;
      if (debug) console.log(conditionName, child.props.value, child.props.debugValue)


      if (typeof child !== "string" && conditionName) {
        if (["If", "ElseIf"].indexOf(conditionName) > -1 && child.props.value) {
          noNeedElse = true;
          if (
            conditionName === "If" ||
            (conditionName === "ElseIf" && !hasOneValidIf)
          ) {
            hasOneValidIf = true;
            resultList.push(child);
          }
        } else if (conditionName === "Else") {
          hasElse = true;
        } else {
          resultList.push(child);
        }
      } else {
        resultList.push(child);
      }
    });
    //如果需要Else，直接给原children，因为其他的If和ElseIf的value都是false，不会显示出来的
    if (!noNeedElse && hasElse) {
      resultList = children;
    }
    if (debug) console.log({noNeedElse, hasElse, resultList})
    return getValidChildren(resultList);
  };

  render() {
    return this.getChildren();
  }
}

//If很简单，判断一下就完事了
class If extends React.Component {
  render() {
    const { children, value } = this.props;
    return value ? getValidChildren(children) : null;
  }
}

If.PropTypes = {
  value: React.PropTypes.any,
  _conditionName: React.PropTypes.string, //打包后不能用type.display获得正确的组件名，所以增加这一项内部控制用
};

If.defaultProps = {
  _conditionName: "If",
};

//ElseIf跟If一样，判断都在Condition里
class ElseIf extends If {}

ElseIf.defaultProps = {
  _conditionName: "ElseIf",
};

//Else直接输出就行了，判断都在Condition里
class Else extends React.Component {
  render() {
    const { children } = this.props;
    return getValidChildren(children);
  }
}

Else.defaultProps = {
  _conditionName: "Else",
};

Condition.If = If;
Condition.ElseIf = ElseIf;
Condition.Else = Else;

export default Condition;
